//**********************************************************************
//	Programmer	-	Sujal Bista
//	File Name	-	GraphicsDX.h
//	Description	:	
//					API handler for Direct X
//**********************************************************************


#include "graphicsDX.h"
#include "picture.h"
#include "utilityFunctions.h"

#ifdef _MSC_VER
	#ifdef _DEBUG
		#include <crtdbg.h>
		#include <stdlib.h>
		#define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__)
		#define new DEBUG_NEW	
	#else
		#define DEBUG_NEW new
	#endif		
#endif

#ifdef _MSC_VER
	#ifdef _DEBUG
		#pragma comment(lib,"d3d11.lib")
		#pragma comment(lib,"d3dcompiler.lib")
		#pragma comment(lib,"d3dx11d.lib")
		#pragma comment(lib,"d3dx9d.lib")
		#pragma comment(lib,"dxerr.lib")
		#pragma comment(lib,"dxguid.lib")

	#else
		#pragma comment(lib,"d3d11.lib")
		#pragma comment(lib,"d3dcompiler.lib")
		#pragma comment(lib,"d3dx11.lib")
		#pragma comment(lib,"d3dx9.lib")
		#pragma comment(lib,"dxerr.lib")
		#pragma comment(lib,"dxguid.lib")
	#endif		
#endif

//helper function that returns resource
ID3D11Resource *getResourceHelper(graphicsDX::resourceBase *bData)
{
	ID3D11Resource *resourceData=NULL;
	using namespace graphicsDefinitions;
	switch(bData->getType())
	{
		case RESOURCE_DIMENSION_TEXTURE2D:
			return ((graphicsDX::texture2DD3D *)bData)->data;
		case RESOURCE_DIMENSION_BUFFER:
			return ((graphicsDX::bufferD3D *)bData)->data;
		case RESOURCE_DIMENSION_TEXTURE1D:
			return ((graphicsDX::texture1DD3D *)bData)->data;
		case RESOURCE_DIMENSION_TEXTURE3D:
			return ((graphicsDX::texture3DD3D *)bData)->data;
			break;
	};
	return NULL;
}

//constructor
graphicsDX::graphicsDX(void):graphicsBase()
{
	//form related variables
	hWnd=0;						// handle to main window

	//dx related variables
	driverType = D3D_DRIVER_TYPE_NULL;
	featureLevel = D3D_FEATURE_LEVEL_11_0;
	pSwapChain = NULL;

	//disable vsync
	syncInterval=0;
}
		
//initilizes the device
bool graphicsDX::init(deviceBase *gDevice, deviceContextBase *dContext, texture2DBase *renderTarget, texture2DBase *depthStencil,renderTargetViewBase *rTargetView,depthStencilViewBase *dStencilView)
{
	using namespace graphicsDefinitions;

	deviceD3D *gDeviceD3D=(deviceD3D *)gDevice;
	deviceContextD3D *dContextD3D=(deviceContextD3D *)dContext;
	texture2DD3D *renderTargetD3D=(texture2DD3D *)renderTarget;
	texture2DD3D *depthStencilD3D=(texture2DD3D *)depthStencil;
	renderTargetViewD3D *rTargetViewD3D=(renderTargetViewD3D *)rTargetView;
	depthStencilViewD3D *dStencilViewD3D=(depthStencilViewD3D *)dStencilView;

	HRESULT hr;
	UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE driverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = ARRAYSIZE( driverTypes );

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
    UINT numFeatureLevels = ARRAYSIZE( featureLevels );

    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory( &sd, sizeof( sd ) );
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
    {
        driverType = driverTypes[driverTypeIndex];
        hr = D3D11CreateDeviceAndSwapChain( NULL, driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
			D3D11_SDK_VERSION, &sd, &pSwapChain, &gDeviceD3D->data, &featureLevel, &dContextD3D->data);
        if( SUCCEEDED( hr ) )
            break;
    }
    if( FAILED( hr ) )
        return false;

 //   // Create a render target view
	//hr = pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&renderTargetD3D->data);
 //   if( FAILED( hr ) )
 //       return false;

	//hr = gDeviceD3D->data->CreateRenderTargetView(renderTargetD3D->data, NULL, &rTargetViewD3D->data);
 //   if( FAILED( hr ) )
 //       return false;

 //   // Create depth stencil texture
 //   texture2DDesc descDepth;
 //   descDepth.width = width;
 //   descDepth.height = height;
 //   descDepth.mipLevels = 1;
 //   descDepth.arraySize = 1;
 //   descDepth.format = DATA_FORMAT_D24_UNORM_S8_UINT;
 //   descDepth.sampleDesc.count = 1;
 //   descDepth.sampleDesc.quality = 0;
 //   descDepth.usage = USAGE_DEFAULT;
 //   descDepth.bindFlags = BIND_FLAG_DEPTH_STENCIL;
 //   descDepth.cpuAccessFlags = 0;
 //   descDepth.miscFlags = 0;

	////texture2DD3D depthStencilBuff;
	//hr=gDeviceD3D->createTexture2D(descDepth,0,0,0,depthStencilD3D);
 //   if( FAILED( hr ) )
 //       return false;

 //   // Create the depth stencil view
 //   D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
 //   ZeroMemory( &descDSV, sizeof(descDSV) );
 //   descDSV.Format = (DXGI_FORMAT)descDepth.format;
 //   descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
 //   descDSV.Texture2D.MipSlice = 0;
	//hr = gDeviceD3D->data->CreateDepthStencilView(depthStencilD3D->data, &descDSV, &dStencilViewD3D->data);
 //   if( FAILED( hr ) )
 //       return false;

	//dContextD3D->data->OMSetRenderTargets( 1, &rTargetViewD3D->data, dStencilViewD3D->data);

	//resizes the output screen
	if(!resize(gDevice,dContext,renderTarget,depthStencil,rTargetView,dStencilView, width,height))
		return false;

	return true;
}
	
//closes the device
bool graphicsDX::close(void)
{
    if(pSwapChain)
		pSwapChain->Release();
    return true;
}

//resizes the output screen
bool graphicsDX::resize(deviceBase *gDevice, deviceContextBase *dContext, texture2DBase *renderTarget, texture2DBase *depthStencil,renderTargetViewBase *rTargetView,depthStencilViewBase *dStencilView, const unsigned int &_width,const unsigned int &_height)
{
	width=_width;
	height=_height;

	using namespace graphicsDefinitions;

	deviceD3D *gDeviceD3D=(deviceD3D *)gDevice;
	deviceContextD3D *dContextD3D=(deviceContextD3D *)dContext;
	texture2DD3D *renderTargetD3D=(texture2DD3D *)renderTarget;
	texture2DD3D *depthStencilD3D=(texture2DD3D *)depthStencil;
	renderTargetViewD3D *rTargetViewD3D=(renderTargetViewD3D *)rTargetView;
	depthStencilViewD3D *dStencilViewD3D=(depthStencilViewD3D *)dStencilView;

	HRESULT hr;

	//clear all the previous textures
	renderTargetD3D->clear();
	depthStencilD3D->clear();
	rTargetViewD3D->clear();
	dStencilViewD3D->clear();

	hr=pSwapChain->ResizeBuffers(1,0,0,DXGI_FORMAT_R8G8B8A8_UNORM,0);
	if( FAILED( hr ) )
        return false;
	
	// Create a render target view
	hr = pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&renderTargetD3D->data);
    if( FAILED( hr ) )
        return false;

	hr = gDeviceD3D->data->CreateRenderTargetView(renderTargetD3D->data, NULL, &rTargetViewD3D->data);
    if( FAILED( hr ) )
        return false;

    // Create depth stencil texture
    texture2DDesc descDepth;
    descDepth.width = width;
    descDepth.height = height;
    descDepth.mipLevels = 1;
    descDepth.arraySize = 1;
    descDepth.format = DATA_FORMAT_D24_UNORM_S8_UINT;
    descDepth.sampleDesc.count = 1;
    descDepth.sampleDesc.quality = 0;
    descDepth.usage = USAGE_DEFAULT;
    descDepth.bindFlags = BIND_FLAG_DEPTH_STENCIL;
    descDepth.cpuAccessFlags = 0;
    descDepth.miscFlags = 0;

	//texture2DD3D depthStencilBuff;
	hr=gDeviceD3D->createTexture2D(descDepth,0,0,0,depthStencilD3D);
    if( FAILED( hr ) )
        return false;

    // Create the depth stencil view
    D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
    ZeroMemory( &descDSV, sizeof(descDSV) );
    descDSV.Format = (DXGI_FORMAT)descDepth.format;
    descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    descDSV.Texture2D.MipSlice = 0;
	hr = gDeviceD3D->data->CreateDepthStencilView(depthStencilD3D->data, &descDSV, &dStencilViewD3D->data);
    if( FAILED( hr ) )
        return false;

	//bind render target to output merger state
	dContextD3D->data->OMSetRenderTargets( 1, &rTargetViewD3D->data, dStencilViewD3D->data);

   	//resizes the output screen
	dContextD3D->resize(width,height);
	
	return true;
}

//swaps back and front buffer
void graphicsDX::swapBuffer(void)
{
	pSwapChain->Present(syncInterval, 0);
}

//sets vsync option
void graphicsDX::setVerticalSync(bool option)
{
	if(option)
		syncInterval=1;
	else
		syncInterval=0;
}

//checks for any error
bool graphicsDX::checkError(void)
{
	return true;
}

//destructor
graphicsDX::~graphicsDX()
{
	//closes the device
	close();
}

//compiles shader for the file
bool graphicsDX::compileShaderFromFile(char* fileName,char *entryPoint, char *shaderModel, blobBase* shData)
{
	bool retVal=true;
	ID3DBlob** ppBlobOut=&((blobD3D *)shData)->data;
	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

	//converts ansi to unicode
	WCHAR* szFileName=ansiToUnicode(fileName);

	ID3DBlob* pErrorBlob;
	HRESULT hr = D3DX11CompileFromFile( szFileName, NULL, NULL, entryPoint, shaderModel, dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
	if( FAILED(hr) )
	{
		if( pErrorBlob != NULL )
			outputDebugString( (char*)pErrorBlob->GetBufferPointer());
		retVal=false;
	}
	if( pErrorBlob ) 
		pErrorBlob->Release();
	delete[] szFileName;
	return retVal;
}

//sets window handler
void graphicsDX::setWindowHandler(const HWND &_hWnd)
{
	hWnd=_hWnd;
}

//create deferred context
bool graphicsDX::deviceD3D::createDeferredContext(deviceContextBase* dcData)
{
	deviceContextD3D* dcDataD3D= (deviceContextD3D *)dcData;

	//create the deferred context
	HRESULT hr = data->CreateDeferredContext(0,&dcDataD3D->data);
	if(FAILED(hr))
        return false;
	return true;
}

//creates vertex shader
bool graphicsDX::deviceD3D::createVertexShader(blobBase* shRawData,shaderVertexBase* shData)
{
	shaderVertexD3D* shDataD3D=(shaderVertexD3D*)shData;
	// Create the vertex shader
	HRESULT hr = data->CreateVertexShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}


//creates hull shader
bool graphicsDX::deviceD3D::createHullShader(blobBase* shRawData,shaderHullBase* shData)
{
	shaderHullD3D* shDataD3D=(shaderHullD3D*)shData;
	// Create the hull shader
	HRESULT hr = data->CreateHullShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}

//creates domain shader
bool graphicsDX::deviceD3D::createDomainShader(blobBase* shRawData,shaderDomainBase* shData)
{
	shaderDomainD3D* shDataD3D=(shaderDomainD3D*)shData;
	// Create the domain shader
	HRESULT hr = data->CreateDomainShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}

//creates geometry shader
bool graphicsDX::deviceD3D::createGeometryShader(blobBase* shRawData,shaderGeometryBase* shData)
{
	shaderGeometryD3D* shDataD3D=(shaderGeometryD3D*)shData;
	// Create the geometry shader
	HRESULT hr = data->CreateGeometryShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}

//creates pixel shader
bool graphicsDX::deviceD3D::createPixelShader(blobBase* shRawData,shaderPixelBase* shData)
{
	shaderPixelD3D* shDataD3D=(shaderPixelD3D*)shData;
	// Create the pixel shader
	HRESULT hr = data->CreatePixelShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}

//creates compute shader
bool graphicsDX::deviceD3D::createComputeShader(blobBase* shRawData,shaderComputeBase* shData)
{
	shaderComputeD3D* shDataD3D=(shaderComputeD3D*)shData;
	// Create the compute shader
	HRESULT hr = data->CreateComputeShader( (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferPointer(), (((graphicsDX::blobD3D *)shRawData)->data)->GetBufferSize(), NULL, &(shDataD3D->data));
    if(FAILED(hr))
        return false;

	return true;
}

//creates input layout
bool graphicsDX::deviceD3D::createInputLayout(inputElementDesc *inputDesc, unsigned int inputDescCount,blobBase *shData,inputLayoutBase *inLayData)
{
	inputLayoutD3D* inLayDataD3D=(inputLayoutD3D*)inLayData;
	blobD3D* shDataD3D=(blobD3D*)shData;
	using namespace graphicsDefinitions;

	D3D11_INPUT_ELEMENT_DESC *inputDescD3D=new D3D11_INPUT_ELEMENT_DESC[inputDescCount];

	for(unsigned int i=0;i<inputDescCount;i++)
	{
		switch(inputDesc[i].type)
		{
			case INPUT_DATA_TYPE_BINORMAL:
				inputDescD3D[i].SemanticName="BINORMAL";
				break;
			case INPUT_DATA_TYPE_BLENDINDICES:
				inputDescD3D[i].SemanticName="BLENDINDICES";
				break;
			case INPUT_DATA_TYPE_BLENDWEIGHT:
				inputDescD3D[i].SemanticName="BLENDWEIGHT";
				break;
			case INPUT_DATA_TYPE_COLOR:
				inputDescD3D[i].SemanticName="COLOR";
				break;
			case INPUT_DATA_TYPE_NORMAL:
				inputDescD3D[i].SemanticName="NORMAL";
				break;
			case INPUT_DATA_TYPE_POSITION:
				inputDescD3D[i].SemanticName="POSITION";
				break;
			case INPUT_DATA_TYPE_POSITIONT:
				inputDescD3D[i].SemanticName="POSITIONT";
				break;
			case INPUT_DATA_TYPE_PSIZE:
				inputDescD3D[i].SemanticName="PSIZE";
				break;
			case INPUT_DATA_TYPE_TANGENT:
				inputDescD3D[i].SemanticName="TANGENT";
				break;
			case INPUT_DATA_TYPE_TEXCOORD:
				inputDescD3D[i].SemanticName="TEXCOORD";
				break;
		}
		inputDescD3D[i].SemanticIndex=inputDesc[i].index;
		inputDescD3D[i].Format=(DXGI_FORMAT)inputDesc[i].format;
		inputDescD3D[i].InputSlot=inputDesc[i].inputSlot;
		inputDescD3D[i].AlignedByteOffset=inputDesc[i].alignedByteOffset;
		inputDescD3D[i].InputSlotClass=(D3D11_INPUT_CLASSIFICATION)inputDesc[i].inputSlotClass;
		inputDescD3D[i].InstanceDataStepRate=inputDesc[i].instanceDataStepRate;
	}

	// Create the input layout
	HRESULT hr = data->CreateInputLayout(inputDescD3D,inputDescCount, shDataD3D->data->GetBufferPointer(),shDataD3D->data->GetBufferSize(), &(inLayDataD3D->data));
	delete[] inputDescD3D;

	if(FAILED(hr))
        return false;

	return true;
}

//creates buffer in gpu
bool graphicsDX::deviceD3D::createBuffer(bufferDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, bufferBase *bData)
{
	bufferD3D *bDataD3D=(bufferD3D *)bData;

	D3D11_BUFFER_DESC bd;
	
    bd.ByteWidth = desc.byteWidth;
	bd.Usage = (D3D11_USAGE) desc.usage;
    bd.BindFlags = desc.bindFlags;
    bd.CPUAccessFlags = desc.cpuAccessFlags;
	bd.MiscFlags=desc.miscFlags;
	bd.StructureByteStride=desc.structureByteStride;

	HRESULT hr;
	if(pSysMem)
	{
		D3D11_SUBRESOURCE_DATA InitData;
		memset(&InitData,0,sizeof(D3D11_SUBRESOURCE_DATA));
		InitData.pSysMem = pSysMem;
		InitData.SysMemPitch=sysMemPitch;
		InitData.SysMemSlicePitch=sysMemSlicePitch;
		
		hr = data->CreateBuffer( &bd, &InitData, &bDataD3D->data);
	}
	else
	{
		hr = data->CreateBuffer( &bd, 0, &bDataD3D->data);
	}
	if( FAILED( hr ) )
		return false;

	return true;
}

//creates 1D texture
bool graphicsDX::deviceD3D::createTexture1D(texture1DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture1DBase *tData)
{
	texture1DD3D *tDataD3D=(texture1DD3D *)tData;

	D3D11_TEXTURE1D_DESC bd;
	bd.Width=desc.width;
	bd.MipLevels=desc.mipLevels;
	bd.ArraySize=desc.arraySize;
	bd.Format=(DXGI_FORMAT)desc.format;
	bd.Usage=(D3D11_USAGE)desc.usage;
	bd.BindFlags=desc.bindFlags;
	bd.CPUAccessFlags=desc.cpuAccessFlags;
	bd.MiscFlags=desc.miscFlags;

	HRESULT hr;
	if(pSysMem)
	{
		D3D11_SUBRESOURCE_DATA InitData;
		memset(&InitData,0,sizeof(D3D11_SUBRESOURCE_DATA));
		InitData.pSysMem = pSysMem;
		InitData.SysMemPitch=sysMemPitch;
		InitData.SysMemSlicePitch=sysMemSlicePitch;
		
		hr = data->CreateTexture1D(&bd, &InitData, &tDataD3D->data);
	}
	else
	{
		hr = data->CreateTexture1D( &bd, 0, &tDataD3D->data);
	}
	if( FAILED( hr ) )
		return false;

	return true;
}
//creates 2D texture
bool graphicsDX::deviceD3D::createTexture2D(texture2DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture2DBase *tData)
{
	texture2DD3D *tDataD3D=(texture2DD3D *)tData;

	D3D11_TEXTURE2D_DESC bd;
	bd.Width=desc.width;
	bd.Height=desc.height;
	bd.MipLevels=desc.mipLevels;
	bd.ArraySize=desc.arraySize;
	bd.Format=(DXGI_FORMAT)desc.format;
	bd.SampleDesc.Count=desc.sampleDesc.count;
	bd.SampleDesc.Quality=desc.sampleDesc.quality;
	bd.Usage=(D3D11_USAGE)desc.usage;
	bd.BindFlags=desc.bindFlags;
	bd.CPUAccessFlags=desc.cpuAccessFlags;
	bd.MiscFlags=desc.miscFlags;

	HRESULT hr;
	if(pSysMem)
	{
		D3D11_SUBRESOURCE_DATA InitData;
		memset(&InitData,0,sizeof(D3D11_SUBRESOURCE_DATA));
		InitData.pSysMem = pSysMem;
		InitData.SysMemPitch=sysMemPitch;
		InitData.SysMemSlicePitch=sysMemSlicePitch;
		
		hr = data->CreateTexture2D(&bd, &InitData, &tDataD3D->data);
	}
	else
	{
		hr = data->CreateTexture2D(&bd, 0, &tDataD3D->data);
	}
	if( FAILED( hr ) )
		return false;

	return true;
}
//creates 3D texture
bool graphicsDX::deviceD3D::createTexture3D(texture3DDesc desc, void *pSysMem, unsigned int sysMemPitch, unsigned int sysMemSlicePitch, texture3DBase *tData)
{
	texture3DD3D *tDataD3D=(texture3DD3D *)tData;

	D3D11_TEXTURE3D_DESC bd;
	bd.Width=desc.width;
	bd.Height=desc.height;
	bd.Depth=desc.depth;
	bd.MipLevels=desc.mipLevels;
	bd.Format=(DXGI_FORMAT)desc.format;
	bd.Usage=(D3D11_USAGE)desc.usage;
	bd.BindFlags=desc.bindFlags;
	bd.CPUAccessFlags=desc.cpuAccessFlags;
	bd.MiscFlags=desc.miscFlags;

	HRESULT hr;
	if(pSysMem)
	{
		D3D11_SUBRESOURCE_DATA InitData;
		memset(&InitData,0,sizeof(D3D11_SUBRESOURCE_DATA));
		InitData.pSysMem = pSysMem;
		InitData.SysMemPitch=sysMemPitch;
		InitData.SysMemSlicePitch=sysMemSlicePitch;
		
		hr = data->CreateTexture3D(&bd, &InitData, &tDataD3D->data);
	}
	else
	{
		hr = data->CreateTexture3D( &bd, 0, &tDataD3D->data);
	}
	if( FAILED( hr ) )
		return false;

	return true;
}

//creates shader resource view from file
bool graphicsDX::deviceD3D::createShaderResourceViewFromFile(char* fileName, shaderResourceViewBase * srvData)
{
	shaderResourceViewD3D *srvDataD3D=(shaderResourceViewD3D *)srvData;

	//converts ansi to unicode
	WCHAR* szFileName=ansiToUnicode(fileName);

	//////////////////////////////////////////////////////////////////////////////

	//picture image;
	////open the texture
	//if(!image.readBMP(fileName))
	//{
	//	char *errString=new char[512];
	//	sprintf(errString,"Cannot open file : %d\n",fileName);
	//	outputDebugString(errString);
	//	delete[] errString;
	//	return false;
	//}

	//texture2D texData;
	//using namespace graphicsDefinitions;

	////create the description
	//graphics::texture2DDesc texDesc;
	//texDesc.width=image.width;
	//texDesc.height=image.height;
	//texDesc.mipLevels=1;
	//texDesc.arraySize=1;
	//texDesc.format=DATA_FORMAT_R8G8B8A8_UNORM;
	//texDesc.sampleDesc.count = 1;
	//texDesc.sampleDesc.quality = 0;
	//texDesc.usage = graphicsDefinitions::USAGE_DEFAULT;
	//texDesc.bindFlags =graphicsDefinitions:: BIND_FLAG_SHADER_RESOURCE;
	//texDesc.cpuAccessFlags = 0;
	//texDesc.miscFlags = 0;

	////create 2D texture
	//createTexture2D(texDesc,0,0,0, &texData);

	////update the texture resource
	//graphics::box updateArea;
	//updateArea.left=0;
	//updateArea.right=image.width;
	//updateArea.top=0;
	//updateArea.bottom=image.height;
	//updateArea.front=0;
	//updateArea.back=1;

	//unsigned char *textureData=NULL;
	////allocate texture data

	////update the resource
	//data->updateSubResource(&texData, NULL, &updateArea, textureData, image.width*image.bytesPerPixel,image.width*image.height*image.bytesPerPixel);

	//
	//////////////////////////////////////////////////////////////////////////////


	//Load the resource
	HRESULT hr = D3DX11CreateShaderResourceViewFromFile(data,szFileName, NULL, NULL, &srvDataD3D->data, NULL);
	
	////////////////////////////////////////////////////////////////////////////
	//D3DX11_IMAGE_LOAD_INFO  imageLoadInfo;
	//imageLoadInfo.Width = D3DX11_DEFAULT;
 //   imageLoadInfo.Height = D3DX11_DEFAULT;
 //   imageLoadInfo.Depth = D3DX11_DEFAULT;
 //   imageLoadInfo.FirstMipLevel = D3DX11_DEFAULT;
 //   imageLoadInfo.MipLevels = D3DX11_DEFAULT;
 //   imageLoadInfo.Usage = (D3D11_USAGE) D3DX11_DEFAULT;
 //   imageLoadInfo.BindFlags = D3DX11_DEFAULT;
 //   imageLoadInfo.CpuAccessFlags = D3DX11_DEFAULT;
 //   imageLoadInfo.MiscFlags = D3DX11_DEFAULT;
 //   imageLoadInfo.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 //   imageLoadInfo.Filter = D3DX11_DEFAULT;
 //   imageLoadInfo.MipFilter = D3DX11_DEFAULT;
 //   imageLoadInfo.pSrcInfo = NULL;

	////Load the resource
	//HRESULT hr = D3DX11CreateShaderResourceViewFromFile(data,szFileName, &imageLoadInfo, NULL, &srvDataD3D->data, NULL);

	/////////////////////////////////////////////////////
	//ID3D11Texture2D * pTexture2D = NULL;
	//ID3D11ShaderResourceView *pSRView = NULL;
	//D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
	//D3D11_TEXTURE2D_DESC desc;

	//// Load the texture and initialize an ID3D11Texture2D object.
	//D3DX11CreateTextureFromFile( data,szFileName, NULL, NULL, (ID3D11Resource**)(&pTexture2D), NULL );

	//// Get a texture description to determine the texture
	//// format of the loaded texture.
	//pTexture2D->GetDesc( &desc );

	//// Fill in the D3D11_SHADER_RESOURCE_VIEW_DESC structure.
	//srvDesc.Format = desc.Format;
	//srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	//srvDesc.Texture2D.MostDetailedMip = 0;
	//srvDesc.Texture2D.MipLevels = desc.MipLevels;

	//// Create the shader resource view.
	//HRESULT hr = data->CreateShaderResourceView( pTexture2D, &srvDesc, &srvDataD3D->data);


	delete[] szFileName;

    if( FAILED( hr ) )
        return false;

	return true;
}

//creates shader resource view. param0, param1, param2, param3 depends on the dimension type. Please refer to dx version for params
bool graphicsDX::deviceD3D::createShaderResourceView(resourceBase *bData, graphicsDefinitions::DATA_FORMAT format, graphicsDefinitions::SRV_DIMENSION dimension, unsigned int param0, unsigned int param1, unsigned int param2, unsigned int param3, shaderResourceViewBase* srvData)
{
	//helper function that returns resource
	ID3D11Resource *resourceData=getResourceHelper(bData);
	if(!resourceData)
		return false;	

	shaderResourceViewD3D *srvDataD3D=(shaderResourceViewD3D *)srvData;

	D3D11_SHADER_RESOURCE_VIEW_DESC desc;
    memset(&desc,0,sizeof(desc));

	//just copy the arguments
	desc.Format=(DXGI_FORMAT)format;
	desc.ViewDimension=(D3D11_SRV_DIMENSION)dimension;
	desc.TextureCubeArray.MostDetailedMip=param0;	//since DX11 uses union, for other types it should be okay
	desc.TextureCubeArray.MipLevels=param1;
	desc.TextureCubeArray.First2DArrayFace=param2;
	desc.TextureCubeArray.NumCubes=param3;

	HRESULT hr = data->CreateShaderResourceView(resourceData,&desc,&srvDataD3D->data);
	
	if( FAILED( hr ) )
        return false;

	return true;
}

//creates unordered access view. param0, param1, param2 depends on the dimension type. Please refer to dx version for params
bool graphicsDX::deviceD3D::createUnorderedAccessView(resourceBase *bData, graphicsDefinitions::DATA_FORMAT format, graphicsDefinitions::UAV_DIMENSION dimension, unsigned int param0, unsigned int param1, unsigned int param2, unorderedAccessViewBase* uavData)
{
	//helper function that returns resource
	ID3D11Resource *resourceData=getResourceHelper(bData);
	if(!resourceData)
		return false;
	
	unorderedAccessViewD3D *uavDataD3D=(unorderedAccessViewD3D *)uavData;
	D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
	memset(&desc,0,sizeof(desc));

	 //just copy the arguments
	desc.Format=(DXGI_FORMAT)format;
	desc.ViewDimension=(D3D11_UAV_DIMENSION)dimension;
	desc.Texture2DArray.MipSlice=param0;	//since DX11 uses union, for other types it should be okay
	desc.Texture2DArray.FirstArraySlice=param1;
	desc.Texture2DArray.ArraySize=param2;

	HRESULT hr = data->CreateUnorderedAccessView(resourceData,&desc,&uavDataD3D->data);
	
	if( FAILED( hr ) )
        return false;

	return true;
}

//creates sampler state
bool graphicsDX::deviceD3D::createSamplerState(graphicsDefinitions::FILTER filter,	graphicsDefinitions::TEXTURE_ADDRESS_MODE addMode[3], float mipLODBias, unsigned int maxAnisotropy, graphicsDefinitions::COMPARISON_FUNC comparisonFunc, float borderColor[4], float minLOD, float maxLOD, samplerStateBase *ssBase)
{
	samplerStateD3D *ssBaseD3D=(samplerStateD3D *)ssBase;

	D3D11_SAMPLER_DESC sampDesc;
    sampDesc.Filter = (D3D11_FILTER) filter;
    sampDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)addMode[0];
    sampDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)addMode[1];
    sampDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)addMode[2];
	sampDesc.MipLODBias = mipLODBias;
	sampDesc.MaxAnisotropy=maxAnisotropy;	
    sampDesc.ComparisonFunc = (D3D11_COMPARISON_FUNC)comparisonFunc;
	memcpy(sampDesc.BorderColor,borderColor,sizeof(float)*4);
    sampDesc.MinLOD = minLOD;
    sampDesc.MaxLOD = maxLOD;

	HRESULT hr = data->CreateSamplerState( &sampDesc, &ssBaseD3D->data);
    if( FAILED( hr ) )
        return false;

	return true;
}

//creates rasterizer state
bool graphicsDX::deviceD3D::createRasterizerState(graphicsDefinitions::FILL_MODE fillMode,graphicsDefinitions::CULL_MODE cullMode,bool frontCounterClockwise,int depthBias,float depthBiasClamp,float slopeScaledDepthBias,bool depthClipEnable, bool scissorEnable, bool multisampleEnable, bool antialiasedLineEnable,	rasterizerStateBase *rsData)
{

	rasterizerStateD3D *rsDataD3D=(rasterizerStateD3D *)rsData;

	D3D11_RASTERIZER_DESC rState;

	rState.FillMode=(D3D11_FILL_MODE)fillMode;
	rState.CullMode=(D3D11_CULL_MODE)cullMode;
	rState.FrontCounterClockwise=frontCounterClockwise;
	rState.DepthBias=depthBias;
	rState.DepthBiasClamp=depthBiasClamp;
	rState.SlopeScaledDepthBias=slopeScaledDepthBias;
	rState.DepthClipEnable=depthClipEnable;
	rState.ScissorEnable=scissorEnable;
	rState.MultisampleEnable=multisampleEnable;
	rState.AntialiasedLineEnable=antialiasedLineEnable;

	//create rasterizer state
	HRESULT hr = data->CreateRasterizerState(&rState,&rsDataD3D->data);	
	if(FAILED(hr))
        return false;

	return true;
}

//creates a blend state
bool graphicsDX::deviceD3D::createBlendState(const blendDesc *bStateDesc,blendStateBase *bStateData)
{
	return false;
}

//resizes the output screen
bool graphicsDX::deviceContextD3D::resize(const unsigned int &_width,const unsigned int &_height)
{
	if(data)
	{
		// Setup the viewport
		D3D11_VIEWPORT vp;
		vp.Width = (FLOAT)_width;
		vp.Height = (FLOAT)_height;
		vp.MinDepth = 0.0f;
		vp.MaxDepth = 1.0f;
		vp.TopLeftX = 0;
		vp.TopLeftY = 0;
		data->RSSetViewports( 1, &vp );
	}

	return true;
}

//Restore all default settings of the device context
void graphicsDX::deviceContextD3D::clearState(void)
{
	//Restore all default settings of the device context
	data->ClearState();
}

//create a command list and record command (d3d context)
bool graphicsDX::deviceContextD3D::finishCommandList(bool restoreDeferredContextState, commandListBase* clData)
{
	commandListD3D* clDataD3D=(commandListD3D *)clData;

	//create the deferred context
	HRESULT hr = data->FinishCommandList(restoreDeferredContextState,&clDataD3D->data);
	if(FAILED(hr))
        return false;
	return true;
}
//queues command from command list to the device  (d3d context)
void graphicsDX::deviceContextD3D::executeCommandList(commandListBase* clData, bool restoreContextState)
{
	commandListD3D* clDataD3D=(commandListD3D *)clData;

	//create the deferred context
	data->ExecuteCommandList(clDataD3D->data,restoreContextState);
}


//sets input layout
void graphicsDX::deviceContextD3D::setInputLayout(inputLayoutBase *inLayData)
{
	inputLayoutD3D* inLayDataD3D=(inputLayoutD3D*)inLayData;
	// Set the input layout
	data->IASetInputLayout(inLayDataD3D->data);

}

//updates sub resource
void graphicsDX::deviceContextD3D::updateSubResource(resourceBase *destinationBuffer, unsigned int destinationSubresource, const box *destinationBox, const void *sourceData, unsigned int sourceRowPitch, unsigned int sourceDepthPitch)
{
	//helper function that returns resource
	ID3D11Resource *resourceData=getResourceHelper(destinationBuffer);
	if(!resourceData)
		return;

	//update ther resource
	data->UpdateSubresource(resourceData, destinationSubresource, (D3D11_BOX*)destinationBox, sourceData, sourceRowPitch, sourceDepthPitch);
}
//copies one buffer to another
void graphicsDX::deviceContextD3D::copyResource( resourceBase *dest, resourceBase *src)
{
	//helper function that returns resource
	ID3D11Resource *resourceDestData=getResourceHelper(dest);
	if(!resourceDestData)
		return;

	//helper function that returns resource
	ID3D11Resource *resourceSrcData=getResourceHelper(src);
	if(!resourceSrcData)
		return;

	//copy resource
	data->CopyResource(resourceDestData,resourceSrcData);
}
//maps the data
void *graphicsDX::deviceContextD3D::map( resourceBase *bData, unsigned int subresource, graphicsDefinitions::MAP mapType,unsigned int &rowPitch, unsigned int &depthPitch)
{
	//helper function that returns resource
	ID3D11Resource *resourceData=getResourceHelper(bData);
	if(!resourceData)
		return NULL;

	D3D11_MAPPED_SUBRESOURCE mappedResource; 
	HRESULT hr = data->Map(resourceData,subresource,(D3D11_MAP)mapType,0,&mappedResource);
	if( FAILED( hr ) )
        return NULL;
	rowPitch=mappedResource.RowPitch;
	depthPitch=mappedResource.DepthPitch;
	return mappedResource.pData;
}
//unmap the data
void graphicsDX::deviceContextD3D::unmap( resourceBase *bData, unsigned int subresource)
{
	//helper function that returns resource
	ID3D11Resource *resourceData=getResourceHelper(bData);
	if(!resourceData)
		return ;

	data->Unmap(resourceData,subresource);
}

//sets vertex buffer
void graphicsDX::deviceContextD3D::setVertexBuffers(unsigned int startSlot,unsigned int bufferCount, bufferBase *bufferDatas,unsigned int strides,unsigned int offsets)
{
	bufferD3D *bufferDatasD3D=(bufferD3D *)bufferDatas;

	ID3D11Buffer **dataBuff=new ID3D11Buffer*[bufferCount];

	//copy all the buffers in the same array
	for(unsigned int i=0;i<bufferCount;i++)
		dataBuff[i]=bufferDatasD3D[i].data;

	data->IASetVertexBuffers( startSlot, bufferCount, dataBuff, &strides, &offsets);

	delete[] dataBuff;
}

//sets index buffer
void graphicsDX::deviceContextD3D::setIndexBuffer(bufferBase *bufferData, graphicsDefinitions::DATA_FORMAT format, unsigned int offset)
{
	bufferD3D *bufferDataD3D=(bufferD3D *)bufferData;

	 // Set index buffer
	data->IASetIndexBuffer(bufferDataD3D->data,(DXGI_FORMAT)format,offset);
}

//sets primitive topology
void graphicsDX::deviceContextD3D::setPrimitiveTopology(graphicsDefinitions::PRIMITIVE_TOPOLOGY topology)
{
	 // Set primitive topology
    data->IASetPrimitiveTopology((D3D11_PRIMITIVE_TOPOLOGY)topology);
}

//Draw non-indexed, non-instanced primitives
void graphicsDX::deviceContextD3D::draw(unsigned int vertexCount,unsigned int startVertexLocation)
{
	data->Draw(vertexCount,startVertexLocation);
}
//draw indexed primitive
void graphicsDX::deviceContextD3D::drawIndexed(unsigned int indexCount,unsigned int startIndexLocation,int baseVertexLocation)
{
	data->DrawIndexed(indexCount,startIndexLocation,baseVertexLocation);
}
//Draw non-indexed, instanced primitives.
void graphicsDX::deviceContextD3D::drawInstanced(unsigned int vertexCountPerInstance,unsigned int instanceCount,unsigned int startVertexLocation,unsigned int startInstanceLocation)
{
	data->DrawInstanced(vertexCountPerInstance,instanceCount,startVertexLocation,startInstanceLocation);
}
//Draw indexed, instanced primitives.
void graphicsDX::deviceContextD3D::drawIndexedInstanced(unsigned int indexCountPerInstance,unsigned int instanceCount,unsigned int startIndexLocation,int baseVertexLocation,unsigned int startInstanceLocation)
{
	data->DrawIndexedInstanced(indexCountPerInstance,instanceCount,startIndexLocation,baseVertexLocation,startInstanceLocation);
}
//Draw instanced, GPU-generated primitives.
void graphicsDX::deviceContextD3D::drawInstancedIndirect(bufferBase *pBufferForArgs,unsigned int alignedByteOffsetForArgs)
{
	data->DrawInstancedIndirect(((bufferD3D *)pBufferForArgs)->data,alignedByteOffsetForArgs);
}
//Draw indexed, instanced, GPU-generated primitives.
void graphicsDX::deviceContextD3D::drawIndexedInstancedIndirect(bufferBase *pBufferForArgs,unsigned int alignedByteOffsetForArgs)
{
	data->DrawIndexedInstancedIndirect(((bufferD3D *)pBufferForArgs)->data,alignedByteOffsetForArgs);
}

//clear the render target
void graphicsDX::deviceContextD3D::clearRenderTargetView(renderTargetViewBase *rTargetView, float *clearColor)
{
	data->ClearRenderTargetView(((renderTargetViewD3D *)rTargetView)->data, clearColor);
}

//Clears the depth-stencil resource
void graphicsDX::deviceContextD3D::clearDepthStencilView(depthStencilViewBase *dStencilView,unsigned int clearFlags, float depth, unsigned int stencil)
{
	data->ClearDepthStencilView( ((depthStencilViewD3D *)dStencilView)->data, clearFlags, depth, (UINT8)stencil);
}


//set constant buffer in pixel shader
void graphicsDX::deviceContextD3D::VSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->VSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}
//set constant buffer in hull shader
void graphicsDX::deviceContextD3D::HSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->HSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}
//set constant buffer in domain shader
void graphicsDX::deviceContextD3D::DSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->DSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}
//set constant buffer in geometry shader
void graphicsDX::deviceContextD3D::GSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->GSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}
//set constant buffer in pixel shader
void graphicsDX::deviceContextD3D::PSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->PSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}
//set constant buffer in compute shader
void graphicsDX::deviceContextD3D::CSSetConstantBuffers(unsigned int startSlot,unsigned int numBuffers, bufferBase *constantBuffers, unsigned int uniformIndex)
{
	bufferD3D *bDataD3D=(bufferD3D *)constantBuffers;

	ID3D11Buffer **ppConstantBuffers=new ID3D11Buffer*[numBuffers];
	
	for(unsigned int i=0;i<numBuffers;i++)
		ppConstantBuffers[i]=bDataD3D[i].data;

	//update the buffer
	data->CSSetConstantBuffers( startSlot, numBuffers, ppConstantBuffers);

	delete[] ppConstantBuffers;
}


//set shader resource in pixel shader
void graphicsDX::deviceContextD3D::VSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;

	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->VSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}
//set shader resource in hull shader
void graphicsDX::deviceContextD3D::HSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;

	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->HSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}
//set shader resource in domain shader
void graphicsDX::deviceContextD3D::DSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;

	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->DSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}
//set shader resource in geometry shader
void graphicsDX::deviceContextD3D::GSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;

	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->GSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}
//set shader resource in pixel shader
void graphicsDX::deviceContextD3D::PSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;

	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->PSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}
//set shader resource in compute shader
void graphicsDX::deviceContextD3D::CSSetShaderResources(unsigned int startSlot,unsigned int numViews, shaderResourceViewBase *shaderResources, unsigned int uniformIndex)
{
	shaderResourceViewD3D *bDataD3D=(shaderResourceViewD3D *)shaderResources;
	ID3D11ShaderResourceView **ppShaderResourceViews=new ID3D11ShaderResourceView*[numViews];
	
	for(unsigned int i=0;i<numViews;i++)
		ppShaderResourceViews[i]=bDataD3D[i].data;

	//update the shader resource
	data->CSSetShaderResources( startSlot, numViews, ppShaderResourceViews);

	delete[] ppShaderResourceViews;
}

//set unordered access view in compute shader
void graphicsDX::deviceContextD3D::CSSetUnorderedAccessViews(unsigned int startSlot,unsigned int numUAVs, unorderedAccessViewBase *uavResources,unsigned int *initialCounts)
{
	unorderedAccessViewD3D *uavResourcesD3D=(unorderedAccessViewD3D *)uavResources;
	ID3D11UnorderedAccessView **ppUnorderedAccessViews=new ID3D11UnorderedAccessView*[numUAVs];
	
	for(unsigned int i=0;i<numUAVs;i++)
		ppUnorderedAccessViews[i]=uavResourcesD3D[i].data;

	//update the shader resource
	data->CSSetUnorderedAccessViews(startSlot, numUAVs, ppUnorderedAccessViews,initialCounts);

	delete[] ppUnorderedAccessViews;
}

//execute direct compute command list from a thread group
void graphicsDX::deviceContextD3D::dispatch(unsigned int threadGroupCountX, unsigned int threadGroupCountY, unsigned int threadGroupCountZ)
{
	//Execute a command list from a thread group
	data->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);

}


//set sampler in pixel shader
void graphicsDX::deviceContextD3D::VSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->VSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}
//set sampler in hull shader
void graphicsDX::deviceContextD3D::HSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->HSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}
//set sampler in domain shader
void graphicsDX::deviceContextD3D::DSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->DSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}
//set sampler in geometry shader
void graphicsDX::deviceContextD3D::GSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->GSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}
//set sampler in pixel shader
void graphicsDX::deviceContextD3D::PSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->PSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}
//set sampler in compute shader
void graphicsDX::deviceContextD3D::CSSetSamplers(unsigned int startSlot,unsigned int numSamplers, samplerStateBase *samplers)
{
	samplerStateD3D *bDataD3D=(samplerStateD3D *)samplers;

	ID3D11SamplerState **ppSamplers=new ID3D11SamplerState*[numSamplers];
	
	for(unsigned int i=0;i<numSamplers;i++)
		ppSamplers[i]=bDataD3D[i].data;

	//update the buffer
	data->CSSetSamplers( startSlot, numSamplers, ppSamplers);

	delete[] ppSamplers;
}

//set vertex shader
void graphicsDX::deviceContextD3D::VSSetShader(shaderVertexBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11VertexShader *pShader=NULL;

	shaderVertexD3D* shaderD3D=(shaderVertexD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->VSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//set hull shader
void graphicsDX::deviceContextD3D::HSSetShader(shaderHullBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11HullShader *pShader=NULL;

	shaderHullD3D* shaderD3D=(shaderHullD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->HSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//set domain shader
void graphicsDX::deviceContextD3D::DSSetShader(shaderDomainBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11DomainShader *pShader=NULL;

	shaderDomainD3D* shaderD3D=(shaderDomainD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->DSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//set geometry shader
void graphicsDX::deviceContextD3D::GSSetShader(shaderGeometryBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11GeometryShader *pShader=NULL;

	shaderGeometryD3D* shaderD3D=(shaderGeometryD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->GSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//set pixel shader
void graphicsDX::deviceContextD3D::PSSetShader(shaderPixelBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11PixelShader *pShader=NULL;

	shaderPixelD3D* shaderD3D=(shaderPixelD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->PSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//set compute shader
void graphicsDX::deviceContextD3D::CSSetShader(shaderComputeBase *shader, classInstanceBase *classInstances,unsigned int numClassInstances)
{
	ID3D11ClassInstance **ppClassInstances=NULL;
	ID3D11ComputeShader *pShader=NULL;

	shaderComputeD3D* shaderD3D=(shaderComputeD3D*)shader;
	classInstanceD3D *classInstancesD3D=(classInstanceD3D *)classInstances;

	
	if(shaderD3D)
		pShader=shaderD3D->data;

	if(numClassInstances)
	{		
		ppClassInstances=new ID3D11ClassInstance*[numClassInstances];
	
		for(unsigned int i=0;i<numClassInstances;i++)
			ppClassInstances[i]=classInstancesD3D[i].data;
	}

	//update the buffer
	data->CSSetShader(pShader,ppClassInstances,numClassInstances);

	delete[] ppClassInstances;
}
//called after all the shaders are set before drawing
void graphicsDX::deviceContextD3D::shaderBegin(void)
{
}
//called after all the drawing is done
void graphicsDX::deviceContextD3D::shaderEnd(void)
{
}
//returns uniform block index. only used in opengl
unsigned int graphicsDX::deviceContextD3D::getUniformBlockIndex(char *name)
{
	return NULL;
}
//returns uniform location. only used in opengl
unsigned int graphicsDX::deviceContextD3D::getUniformLocation(char *name)
{
	return NULL;
}

//sets rasterizer state
void graphicsDX::deviceContextD3D::RSSetState(rasterizerStateBase *rsData)
{
	rasterizerStateD3D *rsDataD3D=(rasterizerStateD3D *)rsData;

	//sets the state
	data->RSSetState(rsDataD3D->data);
}


